package com.ssm.basis.service.office;

import com.ssm.basis.service.exception.CustomException;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StreamUtils;

import java.io.*;
import java.util.Enumeration;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import static org.springframework.util.ResourceUtils.getFile;

public abstract class WordUtil {
    static final String WORD = "word/document.xml";
    static Configuration configuration;

    public static byte[] createWordBytes(String wordPath, Map<String, Object> dataModel) {
        // 获取 zip 文件
        File wordFile = null;
        try {
            // wordFile = new ClassPathResource(wordPath).getFile();
            wordFile = getFile(ResourceUtils.CLASSPATH_URL_PREFIX + wordPath);
        } catch (FileNotFoundException e) {
            throw new CustomException(e);
        }

        // 获取 zip 中的指定文件
        // InputStream read = readFileInZip(wordFile, WORD);
        // 模板数据填充到获取的文件
        // Template template = new Template("fileName", new InputStreamReader(read), cfg);
        // ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // template.process(dataModel, new OutputStreamWriter(baos));
        // InputStream replaceFileStream = new ByteArrayInputStream(baos.toByteArray()); // 输出流转输入流
        // 用填充数据后的新文件替换 zip 中的原文件
        // return replaceFileInZip(zipFile, WORD, replaceFileStream).toByteArray();

        return replaceFileInZip(wordFile, WORD, dataModel).toByteArray();
    }

    /**
     * 用数据替换 zip 中文件(Template 模板文件)的内容
     *
     * @param file            zip 文件
     * @param replaceFilePath 要替换的文件路径
     * @param dataModel       模型数据
     * @return 新 zip 压缩包文件流
     */
    public static FastByteArrayOutputStream replaceFileInZip(File file, String replaceFilePath, Map<String, Object> dataModel) {
        try {
            FastByteArrayOutputStream fbaos = new FastByteArrayOutputStream();
            ZipOutputStream zos = new ZipOutputStream(fbaos); // 新 zip 文件

            ZipFile zipFile = new ZipFile(file); // 原 zip 文件
            Enumeration<? extends ZipEntry> entries = zipFile.entries();
            ZipEntry zipEntry;
            InputStream zipEntryInputStream;
            while (entries.hasMoreElements()) {
                zipEntry = entries.nextElement();

                zos.putNextEntry(new ZipEntry(zipEntry.getName()));
                zipEntryInputStream = zipFile.getInputStream(zipEntry);
                if (replaceFilePath.equalsIgnoreCase(zipEntry.getName())) {
                    Template template = new Template("fileName", new InputStreamReader(zipEntryInputStream), configuration);
                    template.process(dataModel, new OutputStreamWriter(zos));
                } else {
                    // zipEntryInputStream.transferTo(zos);
                    StreamUtils.copy(zipEntryInputStream, zos);
                }
                zipEntryInputStream.close();
                zos.closeEntry();
            }

            zos.close();
            return fbaos;
        } catch (TemplateException | IOException e) {
            throw new CustomException(e);
        }
    }

    @Autowired
    void setConfiguration(Configuration configuration) {
        WordUtil.configuration = configuration;
    }
}
